package com.icekrvams.air.firebase.fcm

import androidx.annotation.WorkerThread
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.messaging.RemoteMessage
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch

object CloudMessaging {

    private val listeners by lazy {
        mutableListOf<FcmListener>()
    }
    private val mainScope by lazy {
        MainScope()
    }

    /**
     * 添加监听器。
     * @param fcmListener 待添加的监听器。
     * @param lifecycleOwner 当前 LifecycleOwner
     * 强烈推荐：如果条件允许，请传入 [lifecycleOwner] 参数，这样可以在生命周期组件销毁时自动移除监听器。
     * 否则请注意在合适的时机手动移除监听器，见 [removeListener]。
     */
    @JvmOverloads
    fun addListener(
        fcmListener: FcmListener,
        lifecycleOwner: LifecycleOwner? = null
    ) {
        listeners.add(fcmListener)
        lifecycleOwner?.lifecycle?.addObserver(object : DefaultLifecycleObserver {
            override fun onDestroy(owner: LifecycleOwner) {
                listeners.remove(fcmListener)
            }
        })
    }

    /**
     * 移除指定监听器。
     * @param fcmListener 待移除的监听器。
     */
    fun removeListener(fcmListener: FcmListener) {
        listeners.remove(fcmListener)
    }

    /**
     * 异步地获取当前token。
     */
    fun getToken(fcmTokenCallback: FcmTokenCallback) {
        FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
            if (!task.isSuccessful) {
                fcmTokenCallback.onFailure()
            } else {
                val token = task.result
                fcmTokenCallback.onSuccess(token)
            }
        }
    }

    /**
     * 接收到FCM后，切换到UI线程，获取data和notification，分别进行回调。
     * @param rawMessage 原生[RemoteMessage]。
     */
    internal fun onMessageReceived(rawMessage: RemoteMessage) {
        if (listeners.isEmpty()) return
        mainScope.launch {
            listeners.forEach { listener ->
                listener.onFcmReceived(rawMessage)
                if (rawMessage.data.isNotEmpty()) {
                    listener.onDataReceived(rawMessage.data, rawMessage)
                }
                rawMessage.notification?.let {
                    listener.onNotificationReceived(it, rawMessage)
                }
            }
        }
    }

    /**
     * CloudMessaging token 更新回调。
     * @param token 更新后的token。
     */
    @WorkerThread
    internal fun onNewToken(token: String) {
        if (listeners.isEmpty()) return
        listeners.forEach { listener ->
            listener.onNewToken(token)
        }
    }
}